﻿
using System;
using System.Collections.Generic;

namespace LxCFD
{
    public partial class LinearSolver : LinearSolverBase
    {
        public SolverTypes SolverType { get; set; } = SolverTypes.AMGV;
        public void SetAMGSolver<T1, T2>(List<T1> provideZone, List<T2> provideContact) where T1 : ScalarHeadBase where T2 : ConnectHeadBase
        {
            foreach (var z in provideZone)
            {
                addAMGSolver(z.Zone.AMGSolver);
            }
            foreach (var c in provideContact)
            {
                addAMGSolver(c.Contact.AMGSolver);
            }
        }
        public void SetAMGSolver(List<AMGInZone> AMGsInZone, List<AMGInContact> AMGsInContact)
        {
            foreach (var z in AMGsInZone)
            {
                addAMGSolver(z);
            }
            foreach (var c in AMGsInContact)
            {
                addAMGSolver(c);
            }
        }
        private void addAMGSolver(AMGInZone AMG)
        {
            if (AMG.MaxCoarseLevel > MaxCoarseLevel)
            {
                MaxCoarseLevel = AMG.MaxCoarseLevel;
            }
            AMGsInZone.Add(AMG);
            if (VariableCount == null)
            {
                VariableCount = new int[AMG.MgZones.Count];
            }
            for (int i1 = 0; i1 < VariableCount.Length; i1++)
            {
                VariableCount[i1] += AMG.MgZones[i1].InnerIndex.CellIDs.GetCount();
            }
        }
        private void addAMGSolver(AMGInContact amg)
        {
            AMGsInContact.Add(amg);
        }
        public void RelaxAndSolve<T1, T2>(List<T1> equations, List<T2> connects) where T1 : MatrixBase where T2 : ConnectBase
        {
            MultiThreads.RunCalTasks((taskIndex) => { foreach (var e in equations) { e.Relax(taskIndex); } });
            switch (SolverType)
            {
                case SolverTypes.AMGV:
                    SolveByJacobi(equations, connects);
                    LinkAMG(equations, connects);
                    AMG_V(connects);//V循环
                    SolveByJacobi(equations, connects);
                    break;
                case SolverTypes.AMGF:
                    SolveByJacobi(equations, connects);
                    LinkAMG(equations, connects);
                    AMG_F(connects);//F循环
                    SolveByJacobi(equations, connects);
                    break;
                case SolverTypes.Jacobi:
                    SolveByJacobi(equations, connects);
                    break;
                case SolverTypes.BiCGSTAB:
                    throw new NotImplementedException();
            }
        }
        public void RelaxAndSolve<T1, T2>(List<T1> scalars, List<T2> connects, SolverTypes solverTypes) where T1 : MatrixBase where T2 : ConnectBase
        {
            this.SolverType = solverTypes;
            RelaxAndSolve(scalars, connects);
        }

        public void SolveExplicit<T1, T2>(List<T1> scalars, List<T2> connects) where T1 : MatrixBase where T2 : ConnectBase
        {
            MultiThreads.RunCalTasks((taskIndex) => { foreach (var c in connects) { c.Copy_xArray(taskIndex); } });
            MultiThreads.RunCalTasks((taskIndex) => { foreach (var s in scalars) { s.CalByExplicit_Step1(taskIndex); } });
            MultiThreads.RunCalTasks((taskIndex) => { foreach (var s in scalars) { s.CalByExplicit_Step2(taskIndex); } });
        }
    }
}
//public void Clear()
//{
//    maxCoarseLevel = 0;
//    AMGsInZone.Clear();
//    AMGsInContact.Clear();
//    if (variableCount != null)
//    {
//        for (int i1 = 0; i1 < variableCount.Length; i1++)
//        {
//            variableCount[i1] = 0;
//        }
//    }
//}